package main

import "fmt"

func main() {
	//使用具有缓存的通道，不会产生死锁
	//withNoDeadLock()
	//使用默认通道产生死锁
	//withDeadLock()
	useSelectNoDeadLock()
}

func withDeadLock() {
	//默认情况下，通道是无缓冲的。
	//每次对一个已打开的、无缓冲的通道写入都会导致goroutine写暂停，
	//直到另一个goroutine从同一个通道读取。
	//同样，读取一个已打开的、无缓冲的通道会导致goroutine读暂停，直到另一个goroutine写入同一个通道
	//所以本实例中，两个通道交叉执行，就会互相等待造成死锁
	chan1 := make(chan int)
	chan2 := make(chan int)

	go func() {
		v := 1
		chan1 <- v
		v2 := <-chan2
		fmt.Println(v, v2)
	}()

	v := 2
	chan2 <- v

	v2 := <-chan1

	fmt.Println(v, v2)
}

func withNoDeadLock() {
	//如果分配了有缓存的通道，那么就没有等待，就可以继续执行，没有死锁
	chan1 := make(chan int, 1)
	chan2 := make(chan int, 1)

	go func() {
		v := 1
		chan1 <- v
		v2 := <-chan2
		fmt.Println(v, v2)
	}()

	v := 2
	chan2 <- v

	v2 := <-chan1

	fmt.Println(v, v2)
}

func useSelectNoDeadLock() {
	chan1 := make(chan int, 1)
	chan2 := make(chan int, 1)

	go func() {
		v := 1
		chan1 <- v
		v2 := <-chan2
		fmt.Println(v, v2)
	}()

	v := 2
	var v2 int

	go func() {
		for {
			select {
			case chan2 <- v:
				fmt.Println("1111")
			case v2 = <-chan1:
				fmt.Println(v2)
			}
		}
	}()
}
